import React from "react";

class HelloClass extends React.Component {
    name = "小明";
    //事件回调函数（标准写法，避免this指向问题）
    //箭头函数的this指向始终保持与外部作用域一样，根本不关心是谁调用的它，
    // 这样写 回调函数中的this指向的时当前的组件实例对象
    clickFn1 = () => {
        console.log("name", this.name);
        console.log("事件1触发了");
    };
    clickFn2() {
        console.log(this); //undefined
        //这里会报错，因为调用该函数的是button的onClick事件
        //则该函数的this指向button，但是
        //如果调用该函数时修改了正确的this指向就不会报错了
        console.log("name", this.name);
        console.log("事件2触发了");
    }
    clickFn3 = (val) => {
        console.log("传递的参数", val);
        console.log("事件3触发了");
    };
    clickFn4(val) {
        console.log("传递的参数", val);
        //调用该函数的是事件4的button的点击事件，所以该函数的this指向的是事件4的button的点击事件
        //而事件4的button的点击事件是箭头函数，它的this同它的父类render中的this（指向的是组件实例）一样，所以相当于是组件实例调用的clickFn4
        //所以clickFn4这个函数里的this也是render中的this，即最终指向组件实例对象，所以能访问到this.name
        console.log("name", this.name);
        console.log("事件4触发了");
    }
    render() {
        return (
            <div>
                <button
                    onClick={function () {
                        // 由react的事件模式可知，调用该函数的是react的事件代理模式,不是button,更不是当前组件实例,所以找不到this
                        console.log(this); //undefined
                    }}>
                    测试button的this
                </button>
                {/* 直接调用箭头函数：不能传参 */}
                <button onClick={this.clickFn1}>事件1-比较推荐</button>
                {/* 直接调用普通函数：不能传参并且会出现this指向问题  */}
                <button onClick={this.clickFn2}>事件2-不推荐</button>
                {/* 直接调用普通函数并使用bind修改this指向，为何使用bind见最下方：不能传参 */}
                <button onClick={this.clickFn2.bind(this)}>
                    修改过this的事件2-不推荐
                </button>

                {/* 推荐以下写法：能传参，没有this指向问题 */}
                {/* 箭头函数方式调用箭头函数 */}
                <button
                    onClick={() => {
                        // 根据箭头函数的性质，这里的this指向的是组件实例
                        console.log(this);
                        //所以这里相当于是组件实例调用的clickFn3
                        this.clickFn3(this.name);
                    }}>
                    事件3-非常推荐
                </button>
                {/* 箭头函数方式调用普通函数 */}
                <button onClick={() => this.clickFn4(this.name)}>
                    事件4-非常推荐
                </button>
            </div>
        );
    }
}
function App() {
    return (
        <div className='App'>
            <HelloClass></HelloClass>
        </div>
    );
}

export default App;

/**
 * 改变this指向：
 * call,改变this指向，并且会自动执行函数即函数不需要加()
 * apply,改变this指向，并且会自动执行函数即函数不需要加()
 * bind,改变this指向，不会自动执行函数，若想自动执行函数需要在后面加()
 */
// const obj1 = {
//   name: "obj1",
//   getName() {
//     console.log(this.name);
//   },
// };
// const obj2 = {
//   name: "obj2",
//   getName() {
//     console.log(this.name);
//   },
// };
// obj1.getName.call(obj2); //obj2
// obj1.getName.apply(obj2); //obj2
// obj1.getName.bind(obj2)(); //obj2
